package model.time;

import java.util.Calendar;

/**
 * Objects of this class are intended to represent a TimeFrame duration of a 
 * single day.
 * @author estoll
 *
 */

public class SingleTimeFrame extends TimeFrame {
	// Structure Inherited from Superclass
	// GettersAndSetters Inherited from Superclass

	// Redefined Methods
	
	public String getType(){
		return "Single";
	}
	
	/**
	 * Double Dispatching. Calls the method isOverlappedFromSingleTimeFrame of
	 * the SingleTimeFrame class, passing this as parameter.
	 * @param withThisObject
	 * @return Boolean
	 */
	public boolean isOverlapped(SingleTimeFrame withThisObject) {
		return withThisObject.isOverlappedFromSingleTimeFrame(this);
	}
	/**
	 * Double Dispatching. Calls the method isOverlappedFromSingleTimeFrame of
	 * the DailyTimeFrame class, passing this as parameter.
	 * @param withThisObject
	 * @return Boolean
	 */
	public boolean isOverlapped(DailyTimeFrame withThisObject) {
		return withThisObject.isOverlappedFromSingleTimeFrame(this);
	}

	/**
	 * Double Dispatching. Calls the method isOverlappedFromSingleTimeFrame of
	 * the WeeklyTimeFrame class, passing this as parameter.
	 * @param withThisObject
	 * @return Boolean
	 */
	public boolean isOverlapped(WeeklyTimeFrame withThisObject) {
		return withThisObject.isOverlappedFromSingleTimeFrame(this);
	}

	/**
	 * Double Dispatching. Calls the method isOverlappedFromSingleTimeFrame of
	 * the MonthlyTimeFrame class, passing this as parameter.
	 * @param withThisObject
	 * @return Boolean
	 */
	public boolean isOverlapped(MonthlyTimeFrame withThisObject) {
		return withThisObject.isOverlappedFromSingleTimeFrame(this);
	}

	
	/**
	 * Answers a remote Calls from a Double Dispatch from the SingleTimeFrame class.
	 * @param withThisObject SingleTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromSingleTimeFrame(SingleTimeFrame his) {
		return ((this.singleDayIsTheSame(his)) && (this.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the DailyTimeFrame class.
	 * @param withThisObject DailyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromDailyTimeFrame(DailyTimeFrame his) {
		return ((this.singleDayIsOverlapped(his)) && (this
				.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the WeeklyTimeFrame class.
	 * @param withThisObject WeeklyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromWeeklyTimeFrame(WeeklyTimeFrame his) {
		return (

		((this.getDayName().equals(his.getDayName())) && (this
				.singleDayIsOverlapped(his))) && (this.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the MonthlyTimeFrame class.
	 * @param withThisObject MonthlyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromMonthlyTimeFrame(MonthlyTimeFrame his) {
		return ((this.singleDayIsOverlapped(his)) && (this
				.timeIsOverlapped(his)));
	}

	/**
	 * Constructs a SingleTimeFrame object validating possible Exceptions.
	 * @param dateStart GregorianCalendar
	 * @param dateEnd GregorianCalendar
	 * @param t	GregorianCalendar, default date values 1900.01.01, only time values are significant
	 * @param t1 GregorianCalendar, default date values 1900.01.01, only time values are significant
	 * @param dayName String day
	 * @throws NullParametersReceivedExpeption Is thrown if any of the needed parameters are null
	 * @throws InvalidMinutesException Is thrown if the minute field of the time values are not 00 or 30
	 * @throws IllegalTimeValuesException Is thrown if timeEnd <= timeStart
	 */
	public SingleTimeFrame(Calendar dateStart, Calendar dateEnd, Calendar t,
			Calendar t1, String dayName)
			throws NullParametersReceivedExpeption, InvalidMinutesException,
			IllegalTimeValuesException {

		if ((dateStart != null) && (dateEnd != null) && (dayName != null)
				&& (t != null) && (t1 != null)) {
			{
				if (((t.get(Calendar.MINUTE) == 30) || (t.get(Calendar.MINUTE) == 00))
						&& ((t1.get(Calendar.MINUTE) == 30) || (t1
								.get(Calendar.MINUTE) == 00))) {
					if ((t.equals(t1)) || (t1.before(t))) {
						throw new IllegalTimeValuesException();
					} else {
						this.setDateStart(dateStart);
						this.setDateEnd(dateStart);
						this.setTimeStart(t);
						this.setTimeEnd(t1);
						this.setDayName(dayName);
					}
				} else {
					throw new InvalidMinutesException();
				}
			}
		} else {
			throw new NullParametersReceivedExpeption();
		}
	}

	public SingleTimeFrame() {
		// TODO Auto-generated constructor stub
		super();
	}
	/**
	 * Returns true if the day of this SingleTimeFrame is included within another subclass of TimeFrame
	 * @param his any subclass of TimeFrame, excluding SingleTimeFrame
	 * @return Boolean
	 */
	public boolean singleDayIsOverlapped(TimeFrame his) {
		return ( // this method should only be used from within a
		// SingleTimeFrame
		(this.getDateStart().after(his.getDateStart()) || this.getDateStart().equals(his.getDateStart()))
				&&   
		(this.getDateStart().before(his.getDateEnd()) || this.getDateStart().equals(his.getDateEnd()))
			);
	}

	/**
	 * Returns if this.dayName is equal to his.dayName
	 * @param his all subclasses of TimeFrame
	 * @return Boolean
	 */
	public boolean singleDayIsTheSame(SingleTimeFrame his) {
		return (((this.getDateStart().get(Calendar.YEAR) == his.getDateStart()
				.get(Calendar.YEAR)) && (this.getDateStart()
				.get(Calendar.MONTH) == his.getDateStart().get(Calendar.MONTH))) && (this
				.getDateStart().get(Calendar.DATE) == his.getDateStart().get(
				Calendar.DATE)));
	}

	

}
